home *** CD-ROM | disk | FTP | other *** search
/ CU Amiga Super CD-ROM 14 / CU Amiga Magazine's Super CD-ROM 14 (1997)(EMAP Images)(GB)(Track 1 of 3)[!][issue 1997-09].iso / CUCD / Programming / Mesa-2.2 / src / lines.c < prev    next >
Encoding:
C/C++ Source or Header  |  1997-03-13  |  23.1 KB  |  861 lines

  1. /* $Id: lines.c,v 1.9 1997/03/08 02:04:27 brianp Exp $ */
  2.  
  3. /*
  4.  * Mesa 3-D graphics library
  5.  * Version:  2.2
  6.  * Copyright (C) 1995-1997  Brian Paul
  7.  *
  8.  * This library is free software; you can redistribute it and/or
  9.  * modify it under the terms of the GNU Library General Public
  10.  * License as published by the Free Software Foundation; either
  11.  * version 2 of the License, or (at your option) any later version.
  12.  *
  13.  * This library is distributed in the hope that it will be useful,
  14.  * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15.  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  16.  * Library General Public License for more details.
  17.  *
  18.  * You should have received a copy of the GNU Library General Public
  19.  * License along with this library; if not, write to the Free
  20.  * Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  21.  */
  22.  
  23.  
  24. /*
  25.  * $Log: lines.c,v $
  26.  * Revision 1.9  1997/03/08 02:04:27  brianp
  27.  * better implementation of feedback function
  28.  *
  29.  * Revision 1.8  1997/02/09 18:44:20  brianp
  30.  * added GL_EXT_texture3D support
  31.  *
  32.  * Revision 1.7  1997/01/09 19:48:00  brianp
  33.  * now call gl_texturing_enabled()
  34.  *
  35.  * Revision 1.6  1996/11/08 02:21:21  brianp
  36.  * added null drawing function for GL_NO_RASTER
  37.  *
  38.  * Revision 1.5  1996/09/27 01:28:56  brianp
  39.  * removed unused variables
  40.  *
  41.  * Revision 1.4  1996/09/25 02:01:54  brianp
  42.  * new texture coord interpolation
  43.  *
  44.  * Revision 1.3  1996/09/15 14:18:10  brianp
  45.  * now use GLframebuffer and GLvisual
  46.  *
  47.  * Revision 1.2  1996/09/15 01:48:58  brianp
  48.  * removed #define NULL 0
  49.  *
  50.  * Revision 1.1  1996/09/13 01:38:16  brianp
  51.  * Initial revision
  52.  *
  53.  */
  54.  
  55.  
  56. #include "bresenhm.h"
  57. #include "context.h"
  58. #include "feedback.h"
  59. #include "interp.h"
  60. #include "lines.h"
  61. #include "dlist.h"
  62. #include "macros.h"
  63. #include "pb.h"
  64. #include "texture.h"
  65. #include "types.h"
  66. #include "vb.h"
  67.  
  68.  
  69.  
  70.  
  71. void gl_LineWidth( GLcontext *ctx, GLfloat width )
  72. {
  73.    if (width<=0.0) {
  74.       gl_error( ctx, GL_INVALID_VALUE, "glLineWidth" );
  75.       return;
  76.    }
  77.    if (INSIDE_BEGIN_END(ctx)) {
  78.       gl_error( ctx, GL_INVALID_OPERATION, "glLineWidth" );
  79.       return;
  80.    }
  81.    ctx->Line.Width = width;
  82.    ctx->NewState |= NEW_RASTER_OPS;
  83. }
  84.  
  85.  
  86.  
  87. void gl_LineStipple( GLcontext *ctx, GLint factor, GLushort pattern )
  88. {
  89.    if (INSIDE_BEGIN_END(ctx)) {
  90.       gl_error( ctx, GL_INVALID_OPERATION, "glLineStipple" );
  91.       return;
  92.    }
  93.    ctx->Line.StippleFactor = CLAMP( factor, 1, 256 );
  94.    ctx->Line.StipplePattern = pattern;
  95.    ctx->NewState |= NEW_RASTER_OPS;
  96. }
  97.  
  98.  
  99.  
  100. /**********************************************************************/
  101. /*****                    Rasterization                           *****/
  102. /**********************************************************************/
  103.  
  104.  
  105. /*
  106.  * There are 4 pairs (RGBA, CI) of line drawing functions:
  107.  *   1. simple:  width=1 and no special rasterization functions (fastest)
  108.  *   2. flat:  width=1, non-stippled, flat-shaded, any raster operations
  109.  *   3. smooth:  width=1, non-stippled, smooth-shaded, any raster operations
  110.  *   4. general:  any other kind of line (slowest)
  111.  */
  112.  
  113.  
  114. /*
  115.  * All line drawing functions have the same arguments:
  116.  * v1, v2 - indexes of first and second endpoints into vertex buffer arrays
  117.  * pv     - provoking vertex: which vertex color/index to use for flat shading.
  118.  */
  119.  
  120.  
  121.  
  122. static void feedback_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  123. {
  124.    struct vertex_buffer *VB = ctx->VB;
  125.    GLfloat x1, y1, z1, w1;
  126.    GLfloat x2, y2, z2, w2;
  127.    GLfloat tex1[4], tex2[4], invq;
  128.    GLfloat invRedScale   = ctx->Visual->InvRedScale;
  129.    GLfloat invGreenScale = ctx->Visual->InvGreenScale;
  130.    GLfloat invBlueScale  = ctx->Visual->InvBlueScale;
  131.    GLfloat invAlphaScale = ctx->Visual->InvAlphaScale;
  132.  
  133.    x1 = VB->Win[v1][0];
  134.    y1 = VB->Win[v1][1];
  135.    z1 = VB->Win[v1][2] / DEPTH_SCALE;
  136.    w1 = VB->Clip[v1][3];
  137.  
  138.    x2 = VB->Win[v2][0];
  139.    y2 = VB->Win[v2][1];
  140.    z2 = VB->Win[v2][2] / DEPTH_SCALE;
  141.    w2 = VB->Clip[v2][3];
  142.  
  143.    invq = 1.0F / VB->TexCoord[v1][3];
  144.    tex1[0] = VB->TexCoord[v1][0] * invq;
  145.    tex1[1] = VB->TexCoord[v1][1] * invq;
  146.    tex1[2] = VB->TexCoord[v1][2] * invq;
  147.    tex1[3] = VB->TexCoord[v1][3];
  148.    invq = 1.0F / VB->TexCoord[v2][3];
  149.    tex2[0] = VB->TexCoord[v2][0] * invq;
  150.    tex2[1] = VB->TexCoord[v2][1] * invq;
  151.    tex2[2] = VB->TexCoord[v2][2] * invq;
  152.    tex2[3] = VB->TexCoord[v2][3];
  153.  
  154.    if (ctx->StippleCounter==0) {
  155.       FEEDBACK_TOKEN( ctx, (GLfloat) GL_LINE_RESET_TOKEN );
  156.    }
  157.    else {
  158.       FEEDBACK_TOKEN( ctx, (GLfloat) GL_LINE_TOKEN );
  159.    }
  160.    if (ctx->Light.ShadeModel==GL_FLAT) {
  161.       GLfloat color[4];
  162.       /* convert color from integer to a float in [0,1] */
  163.       color[0] = (GLfloat) VB->Color[pv][0] * invRedScale;
  164.       color[1] = (GLfloat) VB->Color[pv][1] * invGreenScale;
  165.       color[2] = (GLfloat) VB->Color[pv][2] * invBlueScale;
  166.       color[3] = (GLfloat) VB->Color[pv][3] * invAlphaScale;
  167.       gl_feedback_vertex( ctx, x1,y1,z1,w1, color,
  168.                           (GLfloat) VB->Index[pv], tex1 );
  169.       gl_feedback_vertex( ctx, x2,y2,z2,w2, color,
  170.                           (GLfloat) VB->Index[pv], tex2 );
  171.    }
  172.    else {
  173.       GLfloat color[4];
  174.       /* convert color from fixed point to a float in [0,1] */
  175.       color[0] = FixedToFloat(VB->Color[v1][0]) * invRedScale;
  176.       color[1] = FixedToFloat(VB->Color[v1][1]) * invGreenScale;
  177.       color[2] = FixedToFloat(VB->Color[v1][2]) * invBlueScale;
  178.       color[3] = FixedToFloat(VB->Color[v1][3]) * invAlphaScale;
  179.       gl_feedback_vertex( ctx, x1,y1,z1,w1, color,
  180.                           (GLfloat) VB->Index[v1], tex1 );
  181.       /* convert color from fixed point to a float in [0,1] */
  182.       color[0] = FixedToFloat(VB->Color[v2][0]) * invRedScale;
  183.       color[1] = FixedToFloat(VB->Color[v2][1]) * invGreenScale;
  184.       color[2] = FixedToFloat(VB->Color[v2][2]) * invBlueScale;
  185.       color[3] = FixedToFloat(VB->Color[v2][3]) * invAlphaScale;
  186.       gl_feedback_vertex( ctx, x2,y2,z2,w2, color,
  187.                           (GLfloat) VB->Index[v2], tex2 );
  188.    }
  189.    ctx->StippleCounter++;
  190. }
  191.  
  192.  
  193.  
  194. static void select_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  195. {
  196.    gl_update_hitflag( ctx, ctx->VB->Win[v1][2] / DEPTH_SCALE );
  197.    gl_update_hitflag( ctx, ctx->VB->Win[v2][2] / DEPTH_SCALE );
  198. }
  199.  
  200.  
  201.  
  202. #if MAX_WIDTH > MAX_HEIGHT
  203. #  define MAXPOINTS MAX_WIDTH
  204. #else
  205. #  define MAXPOINTS MAX_HEIGHT
  206. #endif
  207.  
  208.  
  209. /*
  210.  * Flat shaded, width=1, non-stippled, color index line.
  211.  */
  212. static void flat_ci_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  213. {
  214.    struct vertex_buffer *VB = ctx->VB;
  215.    struct pixel_buffer *PB = ctx->PB;
  216.    GLint x1 = (GLint) VB->Win[v1][0];
  217.    GLint y1 = (GLint) VB->Win[v1][1];
  218.    GLint x2 = (GLint) VB->Win[v2][0];
  219.    GLint y2 = (GLint) VB->Win[v2][1];
  220.    GLint n;
  221.  
  222.    PB_SET_INDEX( ctx, PB, VB->Index[pv] );
  223.  
  224.    /* compute pixel locations */
  225.    n = gl_bresenham( ctx, x1, y1, x2, y2, PB->x+PB->count, PB->y+PB->count );
  226.  
  227.    /* interpolate z values */
  228.    if (ctx->Depth.Test) {
  229.       GLdepth *zptr = PB->z + PB->count;
  230.       GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
  231.       GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
  232.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  233.    }
  234.  
  235.    PB->count += n;
  236.    PB_CHECK_FLUSH( ctx, PB );
  237. }
  238.  
  239.  
  240. /*
  241.  * Flat-shaded, width=1, non-stippled, rgba line.
  242.  */
  243. static void flat_rgba_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  244. {
  245.    struct vertex_buffer *VB = ctx->VB;
  246.    struct pixel_buffer *PB = ctx->PB;
  247.    GLint x1 = (GLint) VB->Win[v1][0];
  248.    GLint y1 = (GLint) VB->Win[v1][1];
  249.    GLint x2 = (GLint) VB->Win[v2][0];
  250.    GLint y2 = (GLint) VB->Win[v2][1];
  251.    GLint n;
  252.  
  253.    /* Note that color components are ints, not fixed point here */
  254.    PB_SET_COLOR( ctx, PB, VB->Color[pv][0], VB->Color[pv][1],
  255.                  VB->Color[pv][2], VB->Color[pv][3] );
  256.  
  257.    /* compute pixel locations */
  258.    n = gl_bresenham( ctx, x1, y1, x2, y2, PB->x+PB->count, PB->y+PB->count );
  259.  
  260.    /* interpolate z values */
  261.    if (ctx->Depth.Test) {
  262.       GLdepth *zptr = PB->z + PB->count;
  263.       GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
  264.       GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
  265.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  266.    }
  267.  
  268.    PB->count += n;
  269.    PB_CHECK_FLUSH( ctx, PB );
  270. }
  271.  
  272.  
  273.  
  274. /*
  275.  * Smooth-shaded, width=1, non-stippled, color index line.
  276.  */
  277. static void smooth_ci_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  278. {
  279.    struct vertex_buffer *VB = ctx->VB;
  280.    struct pixel_buffer *PB = ctx->PB;
  281.    GLint x1 = (GLint) VB->Win[v1][0];
  282.    GLint y1 = (GLint) VB->Win[v1][1];
  283.    GLint x2 = (GLint) VB->Win[v2][0];
  284.    GLint y2 = (GLint) VB->Win[v2][1];
  285.    GLint n;
  286.  
  287.    /* compute pixel locations */
  288.    n = gl_bresenham( ctx, x1, y1, x2, y2, PB->x+PB->count, PB->y+PB->count );
  289.  
  290.    /* interpolate z values */
  291.    if (ctx->Depth.Test) {
  292.       GLdepth *zptr = PB->z + PB->count;
  293.       GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
  294.       GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
  295.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  296.    }
  297.  
  298.    /* interpolate index */
  299.    gl_interpolate_i( n, (GLint) VB->Index[v1], (GLint) VB->Index[v2],
  300.                      (GLint *) PB->i+PB->count );
  301.  
  302.    PB->count += n;
  303.    PB_CHECK_FLUSH( ctx, PB );
  304. }
  305.  
  306.  
  307. /*
  308.  * Smooth-shaded, width=1, non-stippled, RGBA line.
  309.  */
  310. static void smooth_rgba_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  311. {
  312.    struct vertex_buffer *VB = ctx->VB;
  313.    struct pixel_buffer *PB = ctx->PB;
  314.    GLint x1 = (GLint) VB->Win[v1][0];
  315.    GLint y1 = (GLint) VB->Win[v1][1];
  316.    GLint x2 = (GLint) VB->Win[v2][0];
  317.    GLint y2 = (GLint) VB->Win[v2][1];
  318.    GLint n;
  319.  
  320.    /* compute pixel locations */
  321.    n = gl_bresenham( ctx, x1, y1, x2, y2, PB->x+PB->count, PB->y+PB->count );
  322.  
  323.    /* interpolate z values */
  324.    if (ctx->Depth.Test) {
  325.       GLdepth *zptr = PB->z + PB->count;
  326.       GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
  327.       GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
  328.       GL_INTERPOLATE_Z( n, z1, z2, zptr );
  329.    }
  330.  
  331.    /* interpolate color, VB->Colors are in fixed point */
  332.    gl_interpolate_rgba( n,
  333.                         VB->Color[v1][0], VB->Color[v2][0], PB->r+PB->count,
  334.                         VB->Color[v1][1], VB->Color[v2][1], PB->g+PB->count,
  335.                         VB->Color[v1][2], VB->Color[v2][2], PB->b+PB->count,
  336.                         VB->Color[v1][3], VB->Color[v2][3], PB->a+PB->count );
  337.  
  338.    PB->count += n;
  339.    PB_CHECK_FLUSH( ctx, PB );
  340. }
  341.  
  342.  
  343.  
  344. /*
  345.  * General CI line:  any width, smooth or flat, stippled, any raster ops.
  346.  */
  347. static void general_ci_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  348. {
  349.    struct vertex_buffer *VB = ctx->VB;
  350.    struct pixel_buffer *PB = ctx->PB;
  351.    GLint x1, y1, x2, y2;
  352.    GLint x[MAXPOINTS], y[MAXPOINTS];
  353.    GLdepth z[MAXPOINTS];
  354.    GLubyte mask[MAXPOINTS];
  355.    GLuint index[MAXPOINTS];
  356.    GLint i, n;
  357.    GLint dx, dy;
  358.  
  359.    x1 = (GLint) VB->Win[v1][0];
  360.    y1 = (GLint) VB->Win[v1][1];
  361.    x2 = (GLint) VB->Win[v2][0];
  362.    y2 = (GLint) VB->Win[v2][1];
  363.  
  364.    /* compute pixel locations */
  365.    if (ctx->Line.StippleFlag) {
  366.       n = gl_stippled_bresenham( ctx, x1, y1, x2, y2, x, y, mask );
  367.    }
  368.    else {
  369.       n = gl_bresenham( ctx, x1, y1, x2, y2, x, y );
  370.       for (i=0;i<n;i++) {
  371.      mask[i] = 1;
  372.       }
  373.    }
  374.  
  375.    if (ctx->Depth.Test) {
  376.       /* interpolate z */
  377.       GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
  378.       GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
  379.       GL_INTERPOLATE_Z( n, z1, z2, z );
  380.    }
  381.  
  382.    if (ctx->Light.ShadeModel==GL_FLAT) {
  383.       GLuint indx = VB->Index[pv];
  384.       for (i=0;i<n;i++) {
  385.      index[i] = indx;
  386.       }
  387.    }
  388.    else {
  389.       /* interpolate index */
  390.       gl_interpolate_i( n, (GLint) VB->Index[v1], (GLint) VB->Index[v2],
  391.                 (GLint *) index );
  392.    }
  393.  
  394.    /* compute delta x and delta y */
  395.    if (x1>x2) {
  396.       dx = x1 - x2;
  397.    }
  398.    else {
  399.       dx = x2 - x1;
  400.    }
  401.    if (y1>y2) {
  402.       dy = y1 - y2;
  403.    }
  404.    else {
  405.       dy = y2 - y1;
  406.    }
  407.  
  408.  
  409.    /* render */
  410.    if (ctx->Line.Width==2.0F) {
  411.       /* special case, easy to optimize */
  412.       if (dx>dy) {
  413.      /* X-major: duplicate pixels in Y direction */
  414.      for (i=0;i<n;i++) {
  415.         if (mask[i]) {
  416.            PB_WRITE_CI_PIXEL( PB, x[i], y[i]-1, z[i], index[i] );
  417.            PB_WRITE_CI_PIXEL( PB, x[i], y[i], z[i], index[i] );
  418.         }
  419.      }
  420.       }
  421.       else {
  422.      /* Y-major: duplicate pixels in X direction */
  423.      for (i=0;i<n;i++) {
  424.         if (mask[i]) {
  425.            PB_WRITE_CI_PIXEL( PB, x[i]-1, y[i], z[i], index[i] );
  426.            PB_WRITE_CI_PIXEL( PB, x[i], y[i], z[i], index[i] );
  427.         }
  428.      }
  429.       }
  430.       PB_CHECK_FLUSH( ctx, PB );
  431.    }
  432.    else {
  433.       GLint width, w0, w1;
  434.       width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  435.       w0 = -width / 2;
  436.       w1 = w0 + width - 1;
  437.  
  438.       if (dx>dy) {
  439.      /* X-major: duplicate pixels in Y direction */
  440.      for (i=0;i<n;i++) {
  441.         if (mask[i]) {
  442.            GLint yy;
  443.            GLint y0 = y[i] + w0;
  444.            GLint y1 = y[i] + w1;
  445.            for (yy=y0;yy<=y1;yy++) {
  446.           PB_WRITE_CI_PIXEL( PB, x[i], yy, z[i], index[i] );
  447.            }
  448.            PB_CHECK_FLUSH( ctx, PB );
  449.         }
  450.      }
  451.       }
  452.       else {
  453.      /* Y-major: duplicate pixels in X direction */
  454.      for (i=0;i<n;i++) {
  455.         if (mask[i]) {
  456.            GLint xx;
  457.            GLint x0 = x[i] + w0;
  458.            GLint x1 = x[i] + w1;
  459.            for (xx=x0;xx<=x1;xx++) {
  460.           PB_WRITE_CI_PIXEL( PB, xx, y[i], z[i], index[i] );
  461.            }
  462.            PB_CHECK_FLUSH( ctx, PB );
  463.         }
  464.      }
  465.       }
  466.    }
  467. }
  468.  
  469.  
  470. /*
  471.  * General RGBA line:  any width, smooth or flat, stippled, any raster ops.
  472.  */
  473. static void general_rgba_line( GLcontext *ctx,
  474.                                GLuint v1, GLuint v2, GLuint pv )
  475. {
  476.    struct vertex_buffer *VB = ctx->VB;
  477.    struct pixel_buffer *PB = ctx->PB;
  478.    GLint x1, y1, x2, y2;
  479.    GLint x[MAXPOINTS], y[MAXPOINTS];
  480.    GLdepth z[MAXPOINTS];
  481.    GLubyte mask[MAXPOINTS];
  482.    GLubyte red[MAXPOINTS], green[MAXPOINTS], blue[MAXPOINTS], alpha[MAXPOINTS];
  483.    GLint i, n;
  484.    GLint dx, dy;
  485.  
  486.    x1 = (GLint) VB->Win[v1][0];
  487.    y1 = (GLint) VB->Win[v1][1];
  488.    x2 = (GLint) VB->Win[v2][0];
  489.    y2 = (GLint) VB->Win[v2][1];
  490.  
  491.    /* compute the line */
  492.    if (ctx->Line.StippleFlag) {
  493.       n = gl_stippled_bresenham( ctx, x1, y1, x2, y2, x, y, mask );
  494.    }
  495.    else {
  496.       n = gl_bresenham( ctx, x1, y1, x2, y2, x, y );
  497.       for (i=0;i<n;i++) {
  498.      mask[i] = 1;
  499.       }
  500.    }
  501.  
  502.    if (ctx->Depth.Test) {
  503.       GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
  504.       GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
  505.       GL_INTERPOLATE_Z( n, z1, z2, z );
  506.    }
  507.  
  508.    if (ctx->Light.ShadeModel==GL_FLAT) {
  509.       GLint r, g, b, a;
  510.       r = VB->Color[pv][0];  /* colors are ints, not fixed point */
  511.       g = VB->Color[pv][1];
  512.       b = VB->Color[pv][2];
  513.       a = VB->Color[pv][3];
  514.       for (i=0;i<n;i++) {
  515.      red[i]   = r;
  516.      green[i] = g;
  517.      blue[i]  = b;
  518.      alpha[i] = a;
  519.       }
  520.    }
  521.    else {
  522.       /* interpolate color, VB->Colors are in fixed point */
  523.       gl_interpolate_rgba( n,
  524.                            VB->Color[v1][0], VB->Color[v2][0], red,
  525.                            VB->Color[v1][1], VB->Color[v2][1], green,
  526.                            VB->Color[v1][2], VB->Color[v2][2], blue,
  527.                            VB->Color[v1][3], VB->Color[v2][3], alpha );
  528.    }
  529.  
  530.    /* compute delta x and delta y */
  531.    if (x1>x2) {
  532.       dx = x1 - x2;
  533.    }
  534.    else {
  535.       dx = x2 - x1;
  536.    }
  537.    if (y1>y2) {
  538.       dy = y1 - y2;
  539.    }
  540.    else {
  541.       dy = y2 - y1;
  542.    }
  543.  
  544.    /* render */
  545.    if (ctx->Line.Width==2.0F) {
  546.       /* special case, easy to optimize */
  547.       if (dx>dy) {
  548.      /* X-major: duplicate pixels in Y direction */
  549.      for (i=0;i<n;i++) {
  550.         if (mask[i]) {
  551.            PB_WRITE_RGBA_PIXEL( PB, x[i], y[i]-1, z[i],
  552.                     red[i], green[i], blue[i], alpha[i] );
  553.            PB_WRITE_RGBA_PIXEL( PB, x[i], y[i], z[i],
  554.                     red[i], green[i], blue[i], alpha[i] );
  555.         }
  556.      }
  557.       }
  558.       else {
  559.      /* Y-major: duplicate pixels in X direction */
  560.      for (i=0;i<n;i++) {
  561.         if (mask[i]) {
  562.            PB_WRITE_RGBA_PIXEL( PB, x[i]-1, y[i], z[i],
  563.                     red[i], green[i], blue[i], alpha[i] );
  564.            PB_WRITE_RGBA_PIXEL( PB, x[i], y[i], z[i],
  565.                     red[i], green[i], blue[i], alpha[i] );
  566.         }
  567.      }
  568.       }
  569.       PB_CHECK_FLUSH( ctx, PB );
  570.    }
  571.    else {
  572.       GLint width, w0, w1;
  573.       width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  574.       w0 = -width / 2;
  575.       w1 = w0 + width - 1;
  576.  
  577.       if (dx>dy) {
  578.      /* X-major: duplicate pixels in Y direction */
  579.      for (i=0;i<n;i++) {
  580.         if (mask[i]) {
  581.            GLint yy;
  582.            GLint y0 = y[i] + w0;
  583.            GLint y1 = y[i] + w1;
  584.            for (yy=y0;yy<=y1;yy++) {
  585.           PB_WRITE_RGBA_PIXEL( PB, x[i], yy, z[i],
  586.                        red[i], green[i], blue[i], alpha[i] );
  587.            }
  588.            PB_CHECK_FLUSH( ctx, PB );
  589.         }
  590.      }
  591.       }
  592.       else {
  593.      /* Y-major: duplicate pixels in X direction */
  594.      for (i=0;i<n;i++) {
  595.         if (mask[i]) {
  596.            GLint xx;
  597.            GLint x0 = x[i] + w0;
  598.            GLint x1 = x[i] + w1;
  599.            for (xx=x0;xx<=x1;xx++) {
  600.           PB_WRITE_RGBA_PIXEL( PB, xx, y[i], z[i],
  601.                        red[i], green[i], blue[i], alpha[i] );
  602.            }
  603.            PB_CHECK_FLUSH( ctx, PB );
  604.         }
  605.      }
  606.       }
  607.    }
  608. }
  609.  
  610.  
  611.  
  612. /*
  613.  * Textured RGBA line:  any width, smooth or flat, stippled, any raster ops
  614.  * with texturing.
  615.  */
  616. static void textured_rgba_line( GLcontext *ctx,
  617.                                 GLuint v1, GLuint v2, GLuint pv )
  618. {
  619.    struct vertex_buffer *VB = ctx->VB;
  620.    struct pixel_buffer *PB = ctx->PB;
  621.    GLint x1, y1, x2, y2;
  622.    GLint x[MAXPOINTS], y[MAXPOINTS];
  623.    GLdepth z[MAXPOINTS];
  624.    GLubyte mask[MAXPOINTS];
  625.    /* Allocate arrays dynamically on Mac */
  626.    DEFARRAY(GLubyte,red,MAXPOINTS);
  627.    DEFARRAY(GLubyte,green,MAXPOINTS);
  628.    DEFARRAY(GLubyte,blue,MAXPOINTS);
  629.    DEFARRAY(GLubyte,alpha,MAXPOINTS);
  630.    DEFARRAY(GLfloat,s,MAXPOINTS);
  631.    DEFARRAY(GLfloat,t,MAXPOINTS);
  632.    DEFARRAY(GLfloat,u,MAXPOINTS);
  633. #if 0
  634.    DEFARRAY(GLfloat,v,MAXPOINTS);
  635. #endif
  636.    GLint i, n;
  637.    GLint dx, dy;
  638.  
  639.    x1 = (GLint) VB->Win[v1][0];
  640.    y1 = (GLint) VB->Win[v1][1];
  641.    x2 = (GLint) VB->Win[v2][0];
  642.    y2 = (GLint) VB->Win[v2][1];
  643.  
  644.    /* compute the line */
  645.    if (ctx->Line.StippleFlag) {
  646.       n = gl_stippled_bresenham( ctx, x1, y1, x2, y2, x, y, mask );
  647.    }
  648.    else {
  649.       n = gl_bresenham( ctx, x1, y1, x2, y2, x, y );
  650.       for (i=0;i<n;i++) {
  651.      mask[i] = 1;
  652.       }
  653.    }
  654.  
  655.    if (ctx->Depth.Test) {
  656.       GLint z1 = (GLint) (VB->Win[v1][2] + ctx->LineZoffset);
  657.       GLint z2 = (GLint) (VB->Win[v2][2] + ctx->LineZoffset);
  658.       GL_INTERPOLATE_Z( n, z1, z2, z );
  659.    }
  660.  
  661.    if (ctx->Light.ShadeModel==GL_FLAT) {
  662.       GLint r, g, b, a;
  663.       r = VB->Color[pv][0];  /* colors are ints, not in fixed point */
  664.       g = VB->Color[pv][1];
  665.       b = VB->Color[pv][2];
  666.       a = VB->Color[pv][3];
  667.       for (i=0;i<n;i++) {
  668.      red[i]   = r;
  669.      green[i] = g;
  670.      blue[i]  = b;
  671.      alpha[i] = a;
  672.       }
  673.    }
  674.    else {
  675.       /* interpolate color, VB->Colors are in fixed point */
  676.       gl_interpolate_rgba( n,
  677.                            VB->Color[v1][0], VB->Color[v2][0], red,
  678.                            VB->Color[v1][1], VB->Color[v2][1], green,
  679.                            VB->Color[v1][2], VB->Color[v2][2], blue,
  680.                            VB->Color[v1][3], VB->Color[v2][3], alpha );
  681.    }
  682.  
  683.    /* interpolate texture coordinates */
  684.    {
  685.       GLfloat w1 = 1.0F / VB->Clip[v1][3];
  686.       GLfloat w2 = 1.0F / VB->Clip[v2][3];
  687.       GLfloat s1 = VB->TexCoord[v1][0] * w1;
  688.       GLfloat s2 = VB->TexCoord[v2][0] * w2;
  689.       GLfloat t1 = VB->TexCoord[v1][1] * w1;
  690.       GLfloat t2 = VB->TexCoord[v2][1] * w2;
  691.       GLfloat u1 = VB->TexCoord[v1][2] * w1;
  692.       GLfloat u2 = VB->TexCoord[v2][2] * w2;
  693.       /* don't interpolate r since we don't do 3-D textures, yet */
  694.       GLfloat q1 = VB->TexCoord[v1][3] * w1;
  695.       GLfloat q2 = VB->TexCoord[v2][3] * w2;
  696.       GLfloat inv_n = 1.0F / (GLfloat) n;
  697.       GLfloat ds = (s2-s1) * inv_n;
  698.       GLfloat dt = (t2-t1) * inv_n;
  699.       GLfloat du = (u2-u1) * inv_n;
  700.       GLfloat dq = (q2-q1) * inv_n;
  701.       for (i=0;i<n;i++) {
  702.          s[i] = s1 / q1;
  703.          t[i] = t1 / q1;
  704.          u[i] = u1 / q1;
  705.          s1 += ds;
  706.          t1 += dt;
  707.          u1 += du;
  708.          q1 += dq;
  709.       }
  710.    }
  711.  
  712.    /* compute delta x and delta y */
  713.    if (x1>x2) {
  714.       dx = x1 - x2;
  715.    }
  716.    else {
  717.       dx = x2 - x1;
  718.    }
  719.    if (y1>y2) {
  720.       dy = y1 - y2;
  721.    }
  722.    else {
  723.       dy = y2 - y1;
  724.    }
  725.  
  726.    /* render */
  727.    if (ctx->Line.Width==2.0F) {
  728.       /* special case, easy to optimize */
  729.       if (dx>dy) {
  730.      /* X-major: duplicate pixels in Y direction */
  731.      for (i=0;i<n;i++) {
  732.         if (mask[i]) {
  733.            PB_WRITE_TEX_PIXEL( PB, x[i], y[i]-1, z[i],
  734.               red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
  735.            PB_WRITE_TEX_PIXEL( PB, x[i], y[i], z[i],
  736.               red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
  737.         }
  738.      }
  739.       }
  740.       else {
  741.      /* Y-major: duplicate pixels in X direction */
  742.      for (i=0;i<n;i++) {
  743.         if (mask[i]) {
  744.            PB_WRITE_TEX_PIXEL( PB, x[i]-1, y[i], z[i],
  745.               red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
  746.            PB_WRITE_TEX_PIXEL( PB, x[i], y[i], z[i],
  747.               red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
  748.         }
  749.      }
  750.       }
  751.       PB_CHECK_FLUSH( ctx, PB );
  752.    }
  753.    else {
  754.       GLint width, w0, w1;
  755.       width = (GLint) CLAMP( ctx->Line.Width, MIN_LINE_WIDTH, MAX_LINE_WIDTH );
  756.       w0 = -width / 2;
  757.       w1 = w0 + width - 1;
  758.  
  759.       if (dx>dy) {
  760.      /* X-major: duplicate pixels in Y direction */
  761.      for (i=0;i<n;i++) {
  762.         if (mask[i]) {
  763.            GLint yy;
  764.            GLint y0 = y[i] + w0;
  765.            GLint y1 = y[i] + w1;
  766.            for (yy=y0;yy<=y1;yy++) {
  767.           PB_WRITE_TEX_PIXEL( PB, x[i], yy, z[i],
  768.                  red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
  769.            }
  770.            PB_CHECK_FLUSH( ctx, PB );
  771.         }
  772.      }
  773.       }
  774.       else {
  775.      /* Y-major: duplicate pixels in X direction */
  776.      for (i=0;i<n;i++) {
  777.         if (mask[i]) {
  778.            GLint xx;
  779.            GLint x0 = x[i] + w0;
  780.            GLint x1 = x[i] + w1;
  781.            for (xx=x0;xx<=x1;xx++) {
  782.           PB_WRITE_TEX_PIXEL( PB, xx, y[i], z[i],
  783.                  red[i], green[i], blue[i], alpha[i], s[i], t[i], u[i] );
  784.            }
  785.            PB_CHECK_FLUSH( ctx, PB );
  786.         }
  787.      }
  788.       }
  789.    }
  790.  
  791.    /* Deallocate dynamic arrays on Mac */
  792.    UNDEFARRAY(red);
  793.    UNDEFARRAY(green);
  794.    UNDEFARRAY(blue);
  795.    UNDEFARRAY(alpha);
  796.    UNDEFARRAY(s);
  797.    UNDEFARRAY(t);
  798.    UNDEFARRAY(u);
  799. #if 0
  800.    UNDEFARRAY(v); 
  801. #endif
  802. }
  803.  
  804.  
  805.  
  806. /*
  807.  * Null rasterizer for measuring transformation speed.
  808.  */
  809. static void null_line( GLcontext *ctx, GLuint v1, GLuint v2, GLuint pv )
  810. {
  811. }
  812.  
  813.  
  814.  
  815. /*
  816.  * Determine which line drawing function to use given the current
  817.  * rendering context.
  818.  */
  819. void gl_set_line_function( GLcontext *ctx )
  820. {
  821.    GLboolean rgbmode = ctx->Visual->RGBAflag;
  822.    /* TODO: antialiased lines */
  823.  
  824.    if (ctx->RenderMode==GL_RENDER) {
  825.       if (ctx->NoRaster) {
  826.          ctx->LineFunc = null_line;
  827.          return;
  828.       }
  829.       if (ctx->Driver.LineFunc) {
  830.          /* Device driver will draw lines. */
  831.          ctx->LineFunc = ctx->Driver.LineFunc;
  832.       }
  833.       else if (gl_texturing_enabled(ctx)) {
  834.      ctx->LineFunc = textured_rgba_line;
  835.       }
  836.       else if (ctx->Line.Width!=1.0 || ctx->Line.StippleFlag
  837.                || ctx->Line.SmoothFlag || ctx->Texture.Enabled) {
  838.      ctx->LineFunc = rgbmode ? general_rgba_line : general_ci_line;
  839.       }
  840.       else {
  841.      if (ctx->Light.ShadeModel==GL_SMOOTH) {
  842.         /* Width==1, non-stippled, smooth-shaded, any raster ops */
  843.         ctx->LineFunc = rgbmode ? smooth_rgba_line : smooth_ci_line;
  844.      }
  845.          else {
  846.         /* Width==1, non-stippled, flat-shaded, any raster ops */
  847.         ctx->LineFunc = rgbmode ? flat_rgba_line : flat_ci_line;
  848.          }
  849.       }
  850.    }
  851.    else if (ctx->RenderMode==GL_FEEDBACK) {
  852.       ctx->LineFunc = feedback_line;
  853.    }
  854.    else {
  855.       /* GL_SELECT mode */
  856.       ctx->LineFunc = select_line;
  857.    }
  858. }
  859.  
  860.  
  861.